home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / macros / eplain / arrow.tex < prev    next >
Text File  |  1992-06-09  |  24KB  |  580 lines

  1. % arrow.tex: macros for commutative diagrams.
  2. % Copyright (C) 1991,1992 Steven T. Smith.
  3. %
  4. % This program is free software; you can redistribute it and/or modify
  5. % it under the terms of the GNU General Public License as published by
  6. % the Free Software Foundation; either version 2, or (at your option)
  7. % any later version.
  8. %
  9. % This program is distributed in the hope that it will be useful,
  10. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. % GNU General Public License for more details.
  13. %
  14. % You should have received a copy of the GNU General Public License
  15. % along with this program; if not, write to the Free Software
  16. % Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. % Version 0   Released for alpha testing, November 16, 1991.
  19. % Version 0.1 Morphism positions for slanted lines improved, Nov. 17, 1991.
  20. % Version 0.11 \biline changed to \bisline for compatible naming. 11/21/91
  21. % Version 0.2 Equate \lft & \rt w. _ and ^ instead of L_{12} & R_{12}. 1/20/92
  22. % Version 1.0 Distributed with Eplain. 1/20/92
  23. % Version 1.1 Purged \newcount's, etc.; Warner ref.; \getch@nnel logic. 4/21/92
  24.  
  25.  
  26. % Syntax: \[arrow](X,Y) or
  27. %         \[arrow](X,Y)\lft{MOR} (morphism placed left of arrow) or
  28. %         \[arrow](X,Y)\rt{MOR} (morphism placed right of arrow)
  29. %
  30. % [arrow] is one of
  31. %    sline     (straight line)
  32. %    dotline   (dotted line)             * Unimplemented
  33. %    arrow     (straight arrow)
  34. %    dotarrow  (dotted arrow)            * Unimplemented
  35. %
  36. % The following allow plain versions and some combination of \lft and \rt.
  37. %    biarrow   (two straight arrows)
  38. %    adjarrow  (two adjoint arrows)
  39. %    bisline   (two straight lines)
  40. %
  41. % Also, for left, right, up, and down mappings:
  42. %
  43. % \mapright     (or \mapright^{f_*}, \mapright_{f_*})
  44. % \mapleft      (ditto)
  45. % \mapup        (use \rt and \lft as above)
  46. % \mapdown      (ditto)
  47. %
  48. % And variants of these (can use combinations of ^/_ and lft/rt):
  49. %
  50. % \bimapright   (two right arrows)
  51. % \bimapleft    (two left arrows)
  52. % \adjmapright  (two adjoint arrows; <- over ->)
  53. % \adjmapleft   (two adjoint arrows; -> over <-)
  54. % \hline        (horizontal line)
  55. % \dothline     (dotted horizontal line)     * Unimplemented
  56. % \bihline      (two horizontal lines)
  57. %
  58. % \bimapdown    (two down arrows)
  59. % \bimapup      (two left arrows)
  60. % \adjmapdown   (two adjoint arrows; down then up)
  61. % \adjmapup     (two adjoint arrows; up then down)
  62. % \vline        (vertical line)
  63. % \dotvline     (dotted vertical line)       * Unimplemented
  64. % \bivline      (two vertical lines)
  65.  
  66. % Use \thinlines temporarily to find the current catcode of @, so we can
  67. % restore it at the end.
  68. \edef\thinlines{\the\catcode`@ }%
  69. \catcode`@ = 11
  70. \let\@oldatcatcode = \thinlines
  71.  
  72. % Adapted LaTeX code for drawing lines and vectors
  73.  
  74. % Note: to ensure compatibility with LaTeX, all LaTeX control
  75. % sequences have been renamed.  Control sequence names containing the
  76. % at sign (@) have been changed to contain an ampersand (&) instead.
  77. \edef\@oldandcatcode{\the\catcode`& }%
  78. \catcode`& = 11
  79.  
  80. % LaTeX macros changed here:
  81. % \line - changed to \drawline
  82. % \vector - changed to \drawvector
  83. % \@badlinearg - simply uses \errmessage now
  84. % \@height, \@width, and \@depth are changed to height, width, and depth
  85. % \@sline and \@svector - changed so that \hbox{\drawline...} yields
  86. %  a box of positive width and positive height for a positive slope
  87. %  and positive depth for a negative slope.
  88. % \@hline and \@hvector - likewise
  89. % \unitlength eliminated; pass dimensions to \drawline and \drawvector.
  90.  
  91. % LaTeX's while loop
  92. \def\&whilenoop#1{}%
  93. \def\&whiledim#1\do #2{\ifdim #1\relax#2\&iwhiledim{#1\relax#2}\fi}%
  94. \def\&iwhiledim#1{\ifdim #1\let\&nextwhile=\&iwhiledim 
  95.         \else\let\&nextwhile=\&whilenoop\fi\&nextwhile{#1}}%
  96.  
  97. % LaTeX's \line and \vector macros:
  98. \newif\if&negarg
  99. \newdimen\&wholewidth
  100. \newdimen\&halfwidth
  101.  
  102. \font\tenln=line10
  103.  
  104. \def\thinlines{\let\&linefnt\tenln \let\&circlefnt\tencirc
  105.   \&wholewidth\fontdimen8\tenln \&halfwidth .5\&wholewidth}%
  106. \def\thicklines{\let\&linefnt\tenlnw \let\&circlefnt\tencircw
  107.   \&wholewidth\fontdimen8\tenlnw \&halfwidth .5\&wholewidth}%
  108.  
  109. \def\drawline(#1,#2)#3{\&xarg #1\relax \&yarg #2\relax \&linelen=#3\relax
  110.   \ifnum\&xarg =0 \&vline \else \ifnum\&yarg =0 \&hline \else \&sline\fi\fi}%
  111.  
  112. \def\&sline{\leavevmode
  113.   \ifnum\&xarg< 0 \&negargtrue \&xarg -\&xarg \&yyarg -\&yarg
  114.   \else \&negargfalse \&yyarg \&yarg \fi
  115.   \ifnum \&yyarg >0 \&tempcnta\&yyarg \else \&tempcnta -\&yyarg \fi
  116.   \ifnum\&tempcnta>6 \&badlinearg \&yyarg0 \fi
  117.   \ifnum\&xarg>6 \&badlinearg \&xarg1 \fi
  118.   \setbox\&linechar\hbox{\&linefnt\&getlinechar(\&xarg,\&yyarg)}%
  119.   \ifnum \&yyarg >0 \let\&upordown\raise \&clnht\z@
  120.   \else\let\&upordown\lower \&clnht \ht\&linechar\fi
  121.   \&clnwd=\wd\&linechar
  122.   \&whiledim \&clnwd <\&linelen \do {%
  123.     \&upordown\&clnht\copy\&linechar
  124.     \advance\&clnht \ht\&linechar
  125.     \advance\&clnwd \wd\&linechar
  126.   }%
  127.   \advance\&clnht -\ht\&linechar
  128.   \advance\&clnwd -\wd\&linechar
  129.   \&tempdima\&linelen\advance\&tempdima -\&clnwd
  130.   \&tempdimb\&tempdima\advance\&tempdimb -\wd\&linechar
  131.   \hskip\&tempdimb \multiply\&tempdima \@m
  132.   \&tempcnta \&tempdima \&tempdima \wd\&linechar \divide\&tempcnta \&tempdima
  133.   \&tempdima \ht\&linechar \multiply\&tempdima \&tempcnta
  134.   \divide\&tempdima \@m
  135.   \advance\&clnht \&tempdima
  136.   \ifdim \&linelen <\wd\&linechar \hskip \wd\&linechar
  137.   \else\&upordown\&clnht\copy\&linechar\fi}%
  138.  
  139. \def\&hline{\vrule height \&halfwidth depth \&halfwidth width \&linelen}%
  140.  
  141. \def\&getlinechar(#1,#2){\&tempcnta#1\relax\multiply\&tempcnta 8
  142.   \advance\&tempcnta -9 \ifnum #2>0 \advance\&tempcnta #2\relax\else
  143.   \advance\&tempcnta -#2\relax\advance\&tempcnta 64 \fi
  144.   \char\&tempcnta}%
  145.  
  146. \def\drawvector(#1,#2)#3{\&xarg #1\relax \&yarg #2\relax
  147.   \&tempcnta \ifnum\&xarg<0 -\&xarg\else\&xarg\fi
  148.   \ifnum\&tempcnta<5\relax \&linelen=#3\relax
  149.     \ifnum\&xarg =0 \&vvector \else \ifnum\&yarg =0 \&hvector
  150.     \else \&svector\fi\fi\else\&badlinearg\fi}%
  151.  
  152. \def\&hvector{\ifnum\&xarg<0 \rlap{\&linefnt\&getlarrow(1,0)}\fi \&hline
  153.   \ifnum\&xarg>0 \llap{\&linefnt\&getrarrow(1,0)}\fi}%
  154.  
  155. \def\&vvector{\ifnum \&yarg <0 \&downvector \else \&upvector \fi}%
  156.  
  157. \def\&svector{\&sline
  158.   \&tempcnta\&yarg \ifnum\&tempcnta <0 \&tempcnta=-\&tempcnta\fi
  159.   \ifnum\&tempcnta <5 
  160.     \if&negarg\ifnum\&yarg>0                   % 3d quadrant; dp > 0
  161.       \llap{\lower\ht\&linechar\hbox to\&linelen{\&linefnt
  162.         \&getlarrow(\&xarg,\&yyarg)\hss}}\else % 4th quadrant; ht > 0
  163.       \llap{\hbox to\&linelen{\&linefnt\&getlarrow(\&xarg,\&yyarg)\hss}}\fi
  164.     \else\ifnum\&yarg>0                        % 1st quadrant; ht > 0
  165.       \&tempdima\&linelen \multiply\&tempdima\&yarg
  166.       \divide\&tempdima\&xarg \advance\&tempdima-\ht\&linechar
  167.       \raise\&tempdima\llap{\&linefnt\&getrarrow(\&xarg,\&yyarg)}\else
  168.       \&tempdima\&linelen \multiply\&tempdima-\&yarg % 2d quadrant; dp > 0
  169.       \divide\&tempdima\&xarg
  170.       \lower\&tempdima\llap{\&linefnt\&getrarrow(\&xarg,\&yyarg)}\fi\fi
  171.   \else\&badlinearg\fi}%
  172.  
  173. \def\&getlarrow(#1,#2){\ifnum #2 =\z@ \&tempcnta='33\else
  174. \&tempcnta=#1\relax\multiply\&tempcnta \sixt@@n \advance\&tempcnta
  175. -9 \&tempcntb=#2\relax\multiply\&tempcntb \tw@
  176. \ifnum \&tempcntb >0 \advance\&tempcnta \&tempcntb\relax
  177. \else\advance\&tempcnta -\&tempcntb\advance\&tempcnta 64
  178. \fi\fi\char\&tempcnta}%
  179.  
  180. \def\&getrarrow(#1,#2){\&tempcntb=#2\relax
  181. \ifnum\&tempcntb < 0 \&tempcntb=-\&tempcntb\relax\fi
  182. \ifcase \&tempcntb\relax \&tempcnta='55 \or 
  183. \ifnum #1<3 \&tempcnta=#1\relax\multiply\&tempcnta
  184. 24 \advance\&tempcnta -6 \else \ifnum #1=3 \&tempcnta=49
  185. \else\&tempcnta=58 \fi\fi\or 
  186. \ifnum #1<3 \&tempcnta=#1\relax\multiply\&tempcnta
  187. 24 \advance\&tempcnta -3 \else \&tempcnta=51\fi\or 
  188. \&tempcnta=#1\relax\multiply\&tempcnta
  189. \sixt@@n \advance\&tempcnta -\tw@ \else
  190. \&tempcnta=#1\relax\multiply\&tempcnta
  191. \sixt@@n \advance\&tempcnta 7 \fi\ifnum #2<0 \advance\&tempcnta 64 \fi
  192. \char\&tempcnta}%
  193.  
  194. \def\&vline{\ifnum \&yarg <0 \&downline \else \&upline\fi}%
  195.  
  196. \def\&upline{\hbox to \z@{\hskip -\&halfwidth \vrule width \&wholewidth
  197.    height \&linelen depth \z@\hss}}%
  198.  
  199. \def\&downline{\hbox to \z@{\hskip -\&halfwidth \vrule width \&wholewidth
  200.    height \z@ depth \&linelen \hss}}%
  201.  
  202. \def\&upvector{\&upline\setbox\&tempboxa\hbox{\&linefnt\char'66}\raise 
  203.      \&linelen \hbox to\z@{\lower \ht\&tempboxa\box\&tempboxa\hss}}%
  204.  
  205. \def\&downvector{\&downline\lower \&linelen
  206.       \hbox to \z@{\&linefnt\char'77\hss}}%
  207.  
  208. \def\&badlinearg{\errmessage{Bad \string\arrow\space argument.}}%
  209.  
  210. %INITIALIZATION
  211. \thinlines
  212.  
  213. % Allocate registers using the rules of p.~346 of {\sl The \TeX book}.
  214. \countdef\&xarg     0
  215. \countdef\&yarg     2
  216. \countdef\&yyarg    4
  217. \countdef\&tempcnta 6
  218. \countdef\&tempcntb 8
  219.  
  220. \dimendef\&linelen  0
  221. \dimendef\&clnwd    2
  222. \dimendef\&clnht    4
  223. \dimendef\&tempdima 6
  224. \dimendef\&tempdimb 8
  225.  
  226. \chardef\@arrbox    0
  227. \chardef\&linechar  2
  228. \chardef\&tempboxa  2           % \&linechar and \&tempboxa don't interfere.
  229.  
  230.  
  231. % Macros for abstract nonsense
  232.  
  233. % Macros for slanted lines and arrows.
  234.  
  235. \let\lft^%
  236. \let\rt_% distinguish between \rt and \lft
  237.  
  238. \newif\if@pslope % test for positive slope
  239. \def\@findslope(#1,#2){\ifnum#1>0
  240.   \ifnum#2>0 \@pslopetrue \else\@pslopefalse\fi \else
  241.   \ifnum#2>0 \@pslopefalse \else\@pslopetrue\fi\fi}%
  242.  
  243. \def\generalsmap(#1,#2){\getm@rphposn(#1,#2)\plnmorph\futurelet\next\addm@rph}%
  244.  
  245. % Put arrow in \@arrbox, then add morphisms later.
  246.  
  247. % Single lines and arrows.
  248. \def\sline(#1,#2){\setbox\@arrbox=\hbox{\drawline(#1,#2){\sarrowlength}}%
  249.   \@findslope(#1,#2)\d@@blearrfalse\generalsmap(#1,#2)}%
  250. \def\arrow(#1,#2){\setbox\@arrbox=\hbox{\drawvector(#1,#2){\sarrowlength}}%
  251.   \@findslope(#1,#2)\d@@blearrfalse\generalsmap(#1,#2)}%
  252.  
  253. % Double lines, arrows, and adjoint arrows.
  254. \newif\ifd@@blearr
  255.  
  256. \def\bisline(#1,#2){\@findslope(#1,#2)%
  257.   \if@pslope \let\@upordown\raise \else \let\@upordown\lower\fi
  258.   \getch@nnel(#1,#2)\setbox\@arrbox=\hbox{\@upordown\@vchannel
  259.     \rlap{\drawline(#1,#2){\sarrowlength}}%
  260.       \hskip\@hchannel\hbox{\drawline(#1,#2){\sarrowlength}}}%
  261.   \d@@blearrtrue\generalsmap(#1,#2)}%
  262. \def\biarrow(#1,#2){\@findslope(#1,#2)%
  263.   \if@pslope \let\@upordown\raise \else \let\@upordown\lower\fi
  264.   \getch@nnel(#1,#2)\setbox\@arrbox=\hbox{\@upordown\@vchannel
  265.     \rlap{\drawvector(#1,#2){\sarrowlength}}%
  266.       \hskip\@hchannel\hbox{\drawvector(#1,#2){\sarrowlength}}}%
  267.   \d@@blearrtrue\generalsmap(#1,#2)}%
  268. \def\adjarrow(#1,#2){\@findslope(#1,#2)%
  269.   \if@pslope \let\@upordown\raise \else \let\@upordown\lower\fi
  270.   \getch@nnel(#1,#2)\setbox\@arrbox=\hbox{\@upordown\@vchannel
  271.     \rlap{\drawvector(#1,#2){\sarrowlength}}%
  272.       \hskip\@hchannel\hbox{\drawvector(-#1,-#2){\sarrowlength}}}%
  273.   \d@@blearrtrue\generalsmap(#1,#2)}%
  274.  
  275. % Morphism placement.
  276.  
  277. % Logic for positioning morphisms on slanted arrows:
  278. % If \lft then
  279. %   \hskip by -\@hmorphdflt
  280. %   if \@pslopetrue then \raise by \@vmorphdflt
  281. %   else \lower by \@vmorphdflt
  282. % Else if \rt then
  283. %   \hskip by \@hmorphdflt
  284. %   if \@pslopetrue then \lower by \@vmorphdflt
  285. %   else \raise by \@vmorphdflt
  286. %
  287. % \@hmorphdflt and \@vmorphdflt defined by \getm@rphposn
  288. % Advance \morphdist by .5\channelwidth if double arrows
  289. %
  290. % Use \@shiftmorph to allow users to move morphisms
  291.  
  292. % Logic for \@shiftmorph:
  293. % If \rtm@rph then
  294. %   if \hmorphposnrt=0 then hshift by\hmorphposn else hshift by\hmorphposnrt
  295. %   if \vmorphposnrt=0 then vshift by\vmorphposn else vshift by\vmorphposnrt
  296. % Else
  297. %   if \hmorphposnlft=0 then hshift by\hmorphposn else hshift by\hmorphposnlft
  298. %   if \vmorphposnlft=0 then vshift by\vmorphposn else vshift by\vmorphposnlft
  299.  
  300. \newif\ifrtm@rph
  301. \def\@shiftmorph#1{\hbox{\setbox0=\hbox{$\scriptstyle#1$}%
  302.   \setbox1=\hbox{\hskip\@hm@rphshift\raise\@vm@rphshift\copy0}%
  303.   \wd1=\wd0 \ht1=\ht0 \dp1=\dp0 \box1}}%
  304. \def\@hm@rphshift{\ifrtm@rph
  305.   \ifdim\hmorphposnrt=\z@\hmorphposn\else\hmorphposnrt\fi \else
  306.   \ifdim\hmorphposnlft=\z@\hmorphposn\else\hmorphposnlft\fi \fi}%
  307. \def\@vm@rphshift{\ifrtm@rph
  308.   \ifdim\vmorphposnrt=\z@\vmorphposn\else\vmorphposnrt\fi \else
  309.   \ifdim\vmorphposnlft=\z@\vmorphposn\else\vmorphposnlft\fi \fi}%
  310.  
  311. \def\addm@rph{\ifx\next\lft\let\temp=\lftmorph\else
  312.   \ifx\next\rt\let\temp=\rtmorph\else\let\temp\relax\fi\fi \temp}%
  313.  
  314. \def\plnmorph{\dimen1\wd\@arrbox \ifdim\dimen1<\z@ \dimen1-\dimen1\fi
  315.   \vcenter{\box\@arrbox}}%
  316. \def\lftmorph\lft#1{\rtm@rphfalse \setbox0=\@shiftmorph{#1}%
  317.   \if@pslope \let\@upordown\raise \else \let\@upordown\lower\fi
  318.   \llap{\@upordown\@vmorphdflt\hbox to\dimen1{\hss % \dimen1=\wd\@arrbox
  319.     \llap{\box0}\hss}\hskip\@hmorphdflt}\futurelet\next\addm@rph}%
  320. \def\rtmorph\rt#1{\rtm@rphtrue \setbox0=\@shiftmorph{#1}%
  321.   \if@pslope \let\@upordown\lower \else \let\@upordown\raise\fi
  322.   \llap{\@upordown\@vmorphdflt\hbox to\dimen1{\hss
  323.     \rlap{\box0}\hss}\hskip-\@hmorphdflt}\futurelet\next\addm@rph}%
  324.  
  325. % Get appropriate shifts for morphisms and double lines at various slopes
  326. % Syntax e.g.: \@getshift(1,2){\@hchannel}{\@vchannel}{\channelwidth}%
  327.  
  328. \def\getm@rphposn(#1,#2){\ifd@@blearr \dimen@\morphdist \advance\dimen@ by
  329.   .5\channelwidth \@getshift(#1,#2){\@hmorphdflt}{\@vmorphdflt}{\dimen@}\else
  330.   \@getshift(#1,#2){\@hmorphdflt}{\@vmorphdflt}{\morphdist}\fi}%
  331.  
  332. \def\getch@nnel(#1,#2){\ifdim\hchannel=\z@ \ifdim\vchannel=\z@
  333.     \@getshift(#1,#2){\@hchannel}{\@vchannel}{\channelwidth}%
  334.     \else \@hchannel\hchannel \@vchannel\vchannel \fi
  335.   \else \@hchannel\hchannel \@vchannel\vchannel \fi}%
  336.  
  337. \def\@getshift(#1,#2)#3#4#5{\dimen@ #5\relax
  338.   \&xarg #1\relax \&yarg #2\relax
  339.   \ifnum\&xarg<0 \&xarg -\&xarg \fi
  340.   \ifnum\&yarg<0 \&yarg -\&yarg \fi
  341.   \ifnum\&xarg<\&yarg \&negargtrue \&yyarg\&xarg \&xarg\&yarg \&yarg\&yyarg\fi
  342.   \ifcase\&xarg \or  % There is no case 0
  343.     \ifcase\&yarg    % case 1
  344.       \dimen@i \z@ \dimen@ii \dimen@ \or % case (1,0)
  345.       \dimen@i .7071\dimen@ \dimen@ii .7071\dimen@ \fi \or
  346.     \ifcase\&yarg    % case 2
  347.       \or % case 0,2 wrong
  348.       \dimen@i .4472\dimen@ \dimen@ii .8944\dimen@ \fi \or
  349.     \ifcase\&yarg    % case 3
  350.       \or % case 0,3 wrong
  351.       \dimen@i .3162\dimen@ \dimen@ii .9486\dimen@ \or
  352.       \dimen@i .5547\dimen@ \dimen@ii .8321\dimen@ \fi \or
  353.     \ifcase\&yarg    % case 4
  354.       \or % case 0,2,4 wrong
  355.       \dimen@i .2425\dimen@ \dimen@ii .9701\dimen@ \or\or
  356.       \dimen@i .6\dimen@ \dimen@ii .8\dimen@ \fi \or
  357.     \ifcase\&yarg    % case 5
  358.       \or % case 0,5 wrong
  359.       \dimen@i .1961\dimen@ \dimen@ii .9801\dimen@ \or
  360.       \dimen@i .3714\dimen@ \dimen@ii .9284\dimen@ \or
  361.       \dimen@i .5144\dimen@ \dimen@ii .8575\dimen@ \or
  362.       \dimen@i .6247\dimen@ \dimen@ii .7801\dimen@ \fi \or
  363.     \ifcase\&yarg    % case 6
  364.       \or % case 0,2,3,4,6 wrong
  365.       \dimen@i .1645\dimen@ \dimen@ii .9864\dimen@ \or\or\or\or
  366.       \dimen@i .6402\dimen@ \dimen@ii .7682\dimen@ \fi \fi
  367.   \if&negarg \&tempdima\dimen@i \dimen@i\dimen@ii \dimen@ii\&tempdima\fi
  368.   #3\dimen@i\relax #4\dimen@ii\relax }%
  369.  
  370. \catcode`\&=4  % Back to alignment tab
  371.  
  372.  
  373. % Macros for horizontal and vertical lines and arrows.
  374. % These macros use an idea from Appendix~D, p.~374 of the Texbook.
  375. % Usage: `\mapright^f', `\mapleft', etc.
  376. %        `\mapdown\lft{f}', `\mapup\rt{g}', `\mapdown', etc.
  377.  
  378. % \toks@ will contain the token sequence that defines the arrow and morphisms;
  379. % ensure that \toks@={\mathop{\vcenter{\smash{horiz. arrow}}}\limits} to start.
  380. \def\generalhmap{\futurelet\next\@generalhmap}%
  381. \def\@generalhmap{\ifx\next^ \let\temp\generalhm@rph\else
  382.   \ifx\next_ \let\temp\generalhm@rph\else \let\temp\m@kehmap\fi\fi \temp}%
  383. \def\generalhm@rph#1#2{\ifx#1^
  384.     \toks@=\expandafter{\the\toks@#1{\rtm@rphtrue\@shiftmorph{#2}}}\else
  385.     \toks@=\expandafter{\the\toks@#1{\rtm@rphfalse\@shiftmorph{#2}}}\fi
  386.   \generalhmap}%
  387. \def\m@kehmap{\mathrel{\smash{\the\toks@}}}%
  388.  
  389. \def\mapright{\toks@={\mathop{\vcenter{\smash{\drawrightarrow}}}\limits}%
  390.   \generalhmap}%
  391. \def\mapleft{\toks@={\mathop{\vcenter{\smash{\drawleftarrow}}}\limits}%
  392.   \generalhmap}%
  393. \def\bimapright{\toks@={\mathop{\vcenter{\smash{\drawbirightarrow}}}\limits}%
  394.   \generalhmap}%
  395. \def\bimapleft{\toks@={\mathop{\vcenter{\smash{\drawbileftarrow}}}\limits}%
  396.   \generalhmap}%
  397. \def\adjmapright{\toks@={\mathop{\vcenter{\smash{\drawadjrightarrow}}}\limits}%
  398.   \generalhmap}%
  399. \def\adjmapleft{\toks@={\mathop{\vcenter{\smash{\drawadjleftarrow}}}\limits}%
  400.   \generalhmap}%
  401. \def\hline{\toks@={\mathop{\vcenter{\smash{\drawhline}}}\limits}%
  402.   \generalhmap}%
  403. \def\bihline{\toks@={\mathop{\vcenter{\smash{\drawbihline}}}\limits}%
  404.   \generalhmap}%
  405.  
  406. \def\drawrightarrow{\hbox{\drawvector(1,0){\harrowlength}}}%
  407. \def\drawleftarrow{\hbox{\drawvector(-1,0){\harrowlength}}}%
  408. \def\drawbirightarrow{\hbox{\raise.5\channelwidth
  409.   \hbox{\drawvector(1,0){\harrowlength}}\lower.5\channelwidth
  410.   \llap{\drawvector(1,0){\harrowlength}}}}%
  411. \def\drawbileftarrow{\hbox{\raise.5\channelwidth
  412.   \hbox{\drawvector(-1,0){\harrowlength}}\lower.5\channelwidth
  413.   \llap{\drawvector(-1,0){\harrowlength}}}}%
  414. \def\drawadjrightarrow{\hbox{\raise.5\channelwidth
  415.   \hbox{\drawvector(-1,0){\harrowlength}}\lower.5\channelwidth
  416.   \llap{\drawvector(1,0){\harrowlength}}}}%
  417. \def\drawadjleftarrow{\hbox{\raise.5\channelwidth
  418.   \hbox{\drawvector(1,0){\harrowlength}}\lower.5\channelwidth
  419.   \llap{\drawvector(-1,0){\harrowlength}}}}%
  420. \def\drawhline{\hbox{\drawline(1,0){\harrowlength}}}%
  421. \def\drawbihline{\hbox{\raise.5\channelwidth
  422.   \hbox{\drawline(1,0){\harrowlength}}\lower.5\channelwidth
  423.   \llap{\drawline(1,0){\harrowlength}}}}%
  424.  
  425. % Vertical arrows are handled differently because there is no \mathop.
  426. % \toks@ will contain the token sequence that defines the arrow and morphisms;
  427. % ensure that \toks@={\vcenter{vertical arrow}} to start.
  428. \def\generalvmap{\futurelet\next\@generalvmap}%
  429. \def\@generalvmap{\ifx\next\lft \let\temp\generalvm@rph\else
  430.   \ifx\next\rt \let\temp\generalvm@rph\else \let\temp\m@kevmap\fi\fi \temp}%
  431. % Prepend or append to \toks@ depending on \rt or \lft.
  432. \toksdef\toks@@=1
  433. \def\generalvm@rph#1#2{\ifx#1\rt % append
  434.     \toks@=\expandafter{\the\toks@
  435.       \rlap{$\vcenter{\rtm@rphtrue\@shiftmorph{#2}}$}}\else % prepend
  436.     \toks@@={\llap{$\vcenter{\rtm@rphfalse\@shiftmorph{#2}}$}}%
  437.     \toks@=\expandafter\expandafter\expandafter{\expandafter\the\expandafter
  438.       \toks@@ \the\toks@}\fi \generalvmap}%
  439. \def\m@kevmap{\the\toks@}%
  440.  
  441. \def\mapdown{\toks@={\vcenter{\drawdownarrow}}\generalvmap}%
  442. \def\mapup{\toks@={\vcenter{\drawuparrow}}\generalvmap}%
  443. \def\bimapdown{\toks@={\vcenter{\drawbidownarrow}}\generalvmap}%
  444. \def\bimapup{\toks@={\vcenter{\drawbiuparrow}}\generalvmap}%
  445. \def\adjmapdown{\toks@={\vcenter{\drawadjdownarrow}}\generalvmap}%
  446. \def\adjmapup{\toks@={\vcenter{\drawadjuparrow}}\generalvmap}%
  447. \def\vline{\toks@={\vcenter{\drawvline}}\generalvmap}%
  448. \def\bivline{\toks@={\vcenter{\drawbivline}}\generalvmap}%
  449.  
  450. \def\drawdownarrow{\hbox to5pt{\hss\drawvector(0,-1){\varrowlength}\hss}}%
  451. \def\drawuparrow{\hbox to5pt{\hss\drawvector(0,1){\varrowlength}\hss}}%
  452. \def\drawbidownarrow{\hbox to5pt{\hss\hbox{\drawvector(0,-1){\varrowlength}}%
  453.   \hskip\channelwidth\hbox{\drawvector(0,-1){\varrowlength}}\hss}}%
  454. \def\drawbiuparrow{\hbox to5pt{\hss\hbox{\drawvector(0,1){\varrowlength}}%
  455.   \hskip\channelwidth\hbox{\drawvector(0,1){\varrowlength}}\hss}}%
  456. \def\drawadjdownarrow{\hbox to5pt{\hss\hbox{\drawvector(0,-1){\varrowlength}}%
  457.   \hskip\channelwidth\lower\varrowlength
  458.   \hbox{\drawvector(0,1){\varrowlength}}\hss}}%
  459. \def\drawadjuparrow{\hbox to5pt{\hss\hbox{\drawvector(0,1){\varrowlength}}%
  460.   \hskip\channelwidth\raise\varrowlength
  461.   \hbox{\drawvector(0,-1){\varrowlength}}\hss}}%
  462. \def\drawvline{\hbox to5pt{\hss\drawline(0,1){\varrowlength}\hss}}%
  463. \def\drawbivline{\hbox to5pt{\hss\hbox{\drawline(0,1){\varrowlength}}%
  464.   \hskip\channelwidth\hbox{\drawline(0,1){\varrowlength}}\hss}}%
  465.  
  466.  
  467. % Macros for setting commutative diagrams.
  468.  
  469. % A macro inspired by Ex.~18.46 of the TeXbook.
  470. \def\commdiag#1{\null\,
  471.   \vcenter{\commdiagbaselines
  472.   \m@th\ialign{\hfil$##$\hfil&&\hfil$\mkern4mu ##$\hfil\crcr
  473.       \mathstrut\crcr\noalign{\kern-\baselineskip}
  474.       #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,}%
  475.  
  476. \def\commdiagbaselines{\baselineskip15pt \lineskip3pt \lineskiplimit3pt }%
  477. % A macro inspired by Francis Borceux's Diagram macros for LaTeX
  478. % (FBORCEUX@BUCLLN11.BITNET).
  479. \def\gridcommdiag#1{\null\,
  480.   \vcenter{\offinterlineskip
  481.   \m@th\ialign{&\vbox to\vgrid{\vss
  482.     \hbox to\hgrid{\hss\smash{$##$}\hss}}\crcr
  483.       \mathstrut\crcr\noalign{\kern-\vgrid}
  484.       #1\crcr\mathstrut\crcr\noalign{\kern-.5\vgrid}}}\,}%
  485.  
  486. % Default parameters
  487. % Define default heights and widths for arrows using the golden ratio.
  488. % Note that 5:3 (for sline) and 3:2 (for vector) approximate this ratio.
  489. \newdimen\harrowlength \harrowlength=60pt
  490. \newdimen\varrowlength \varrowlength=.618\harrowlength
  491. \newdimen\sarrowlength \sarrowlength=\harrowlength
  492.  
  493. % Morphism placement
  494. \newdimen\hmorphposn \hmorphposn=\z@
  495. \newdimen\vmorphposn \vmorphposn=\z@
  496. \newdimen\morphdist  \morphdist=4pt
  497.  
  498. \dimendef\@hmorphdflt 0       % These two dimensions are
  499. \dimendef\@vmorphdflt 2       % defined by \getm@rphposn
  500.  
  501. \newdimen\hmorphposnrt  \hmorphposnrt=\z@
  502. \newdimen\hmorphposnlft \hmorphposnlft=\z@
  503. \newdimen\vmorphposnrt  \vmorphposnrt=\z@
  504. \newdimen\vmorphposnlft \vmorphposnlft=\z@
  505. \let\hmorphposnup=\hmorphposnrt
  506. \let\hmorphposndn=\hmorphposnlft
  507. \let\vmorphposnup=\vmorphposnrt
  508. \let\vmorphposndn=\vmorphposnlft
  509.  
  510. % Default grid size for \gridcommdiag
  511. \newdimen\hgrid \hgrid=15pt
  512. \newdimen\vgrid \vgrid=15pt
  513.  
  514. % Horizontal and vertical distance between double lines and arrows. 
  515. \newdimen\hchannel  \hchannel=0pt
  516. \newdimen\vchannel  \vchannel=0pt
  517. \newdimen\channelwidth \channelwidth=3pt
  518.  
  519. \dimendef\@hchannel 0         % Defined via the
  520. \dimendef\@vchannel 2         % macro \getch@nnel
  521.  
  522. \catcode`& = \@oldandcatcode
  523. \catcode`@ = \@oldatcatcode
  524.  
  525.  
  526. % Some examples
  527.  
  528. %\parskip=20pt
  529. %
  530. %The first example:
  531. %$$\commdiag{A&\mapright^f&B&\mapleft^g&C\cr
  532. %\mapdown\lft\psi&\arrow(3,-2)\rt s&\mapup\rt\phi&
  533. %\arrow(-3,2)\lft l&\mapdown\rt\theta\cr
  534. %D&\mapright_h&E&\mapleft_{\int_0^t{\bf A}\,d\sigma}&F\cr}$$
  535. %
  536. %
  537. %Covering homotopy property (Bott and Tu, {\it Differential Forms in
  538. %Algebraic Topology}):
  539. %$$\commdiag{Y&\mapright^f&E\cr \mapdown&\arrow(3,2)\lft{f_t}&\mapdown\cr
  540. %Y\times I&\mapright^{\bar f_t}&X}$$
  541. %
  542. %
  543. %Universal mapping property (Warner, {\it Foundations of Differentiable
  544. %Manifolds and Lie Groups}): $$\varrowlength=20pt
  545. %\commdiag{V\otimes W\cr \mapup\lft\phi&\arrow(3,-1)\rt{\tilde l}\cr
  546. %V\times W&\mapright^l&U\cr}$$
  547. %
  548. %
  549. %A cube (Francis Borceux):
  550. %$$\harrowlength=48pt \varrowlength=48pt \sarrowlength=20pt
  551. %\def\cross#1#2{\setbox0=\hbox{$#1$}%
  552. %  \hbox to\wd0{\hss\hbox{$#2$}\hss}\llap{\unhbox0}}
  553. %\gridcommdiag{&&B&&\mapright^b&&D\cr
  554. %&\arrow(1,1)\lft a&&&&\arrow(1,1)\lft d\cr
  555. %A&&\cross{\hmorphposn=12pt\mapright^c}{\vmorphposn=-12pt\mapdown\lft f}
  556. %&&C&&\mapdown\rt h\cr\cr
  557. %\mapdown\lft e&&F&&\cross{\hmorphposn=-12pt\mapright_j}
  558. %{\vmorphposn=12pt\mapdown\rt g}&&H\cr
  559. %&\arrow(1,1)\lft i&&&&\arrow(1,1)\rt l\cr
  560. %E&&\mapright_k&&G\cr}$$
  561. %
  562. %Zassenhaus's Butterfly Lemma (Lang, {\it Algebra}):
  563. %$$\hgrid=16pt \vgrid=8pt \sarrowlength=32pt
  564. %\def\cross#1#2{\setbox0=\hbox{$#1$}%
  565. %  \hbox to\wd0{\hss\hbox{$#2$}\hss}\llap{\unhbox0}}
  566. %\def\l#1{\llap{$#1$\hskip.5em}}
  567. %\def\r#1{\rlap{\hskip.5em$#1$}}
  568. %\gridcommdiag{&&U&&&&V\cr &&\bullet&&&&\bullet\cr
  569. %&&\sarrowlength=16pt\sline(0,1)&&&&\sarrowlength=16pt\sline(0,1)\cr
  570. %&&\l{u(U\cap V)}\bullet&&&&\bullet\r{(U\cap V)v}\cr
  571. %&&&\sline(2,-1)&&\sline(2,1)\cr
  572. %&&\cross{=}{\sline(0,1)}&&\bullet&&\cross{=}{\sline(0,1)}\cr\cr
  573. %&&\l{^{\textstyle u(U\cap v)}}\bullet&&\cross{=}{\sline(0,1)}&&
  574. % \bullet\r{^{\textstyle(u\cap V)v}}\cr
  575. %&\sline(2,1)&&\sline(2,-1)&&\sline(2,1)&&\sline(2,-1)\cr
  576. %\l{u}\bullet&&&&\bullet&&&&\bullet\r{v}\cr
  577. %&\sline(2,-1)&&\sline(2,1)&&\sline(2,-1)&&\sline(2,1)\cr
  578. %&&\bullet&&&&\bullet\cr &&u\cap V&&&&U\cap v\cr}$$
  579.